/*
*
==============================================================================
*  Name        : 
*  Part of     : Omen Game Engine - Autodesk 3ds Studio .3ds file loader
*  Description : 
*  Version     : 1.0
*
*  Copyright (c) 2013 Lauri Kortevaara.
* 
==============================================================================
*/

#pragma once

/// Plugin_3ds Headers
#include "Config.h"

/// Omen Headers
#include <IOmenModelFileReader.h>
#include <OmenDataTypes.h>

#include <IOmenScene.h>
#include <IOmenModel.h>
#include <IOmenMesh.h>
#include <IOmenMaterial.h>
#include <IOmenFactory.h>

#include "ChunkTypes.h"

/// STL Headers
#include <string>
#include <vector>

namespace Omen
{
    /// 3ds file reader
  class PLUGIN_3DS_API Model_3DS_Reader : public IModelFileReader 
  {
    private:
        
        typedef struct
        {
            WORD        chunkId;          /// The id is 2 byte long identifier of the Chunk
            DWORD       chunkLength;      /// The length of 
            BYTE*       ptrChunk;         /// The pointer to this Chunk in the file
            BYTE*       ptrChunkData;     /// The pointer to this Chunk's data
        } Chunk;

    public: 
        Model_3DS_Reader();
        Model_3DS_Reader( const std::wstring& filename );
        Model_3DS_Reader( const Model_3DS_Reader& other );
        virtual ~Model_3DS_Reader();                                                        /// <summary>Destroys a 3ds archive reader</summary>

        virtual bool canRead( const std::wstring& filename );                               /// <summary>Returns true if this reader can read the given file</summary>
        virtual bool loadFile();                                                            /// <summary>Reads the contents of the model file</summary>

        virtual unsigned long getSceneCount() const;                                        /// <summary>Get number of Scenes in the model-file</summary>
        virtual bool getScenes( IScene** const& pListScenes, unsigned int maxSize ) const;  /// <summary>Get the Scenes</summary>
  protected:
        bool readNextChunk( BYTE*& ptrNextChunk, Chunk* nextChunk );                        /// Reads the Chunk at given address and returns the data in nextchunk
        bool readMainChunk( BYTE*& ptrChunk, Chunk* pChunk );
        bool readEditorChunk( BYTE*& ptrChunk, Chunk* pChunk );
        bool readSubChunk( BYTE*& ptrChunk, Chunk* pChunk );
        bool readMaterialChunk( BYTE*& ptrChunk, Chunk* pChunk );
        bool readKeyframerChunk( BYTE*& ptrChunk, Chunk* pChunk );

        bool getChunkData( BYTE* ptrChunk, Chunk* pChunk );

        // Factory functions
        Omen::IOmenFactory& factory();
        Omen::IScene* newScene();
        Omen::IModel* newModel();
        Omen::IMesh*  newMesh();
  private:
      BYTE*         m_buffer;
      unsigned long m_bufferSize;

      #pragma warning(disable:4251) // Disable warning about private member variable needs to have dll-interface to be used by clients of class 'this'
      std::wstring  m_fileName;

      std::vector< Omen::IScene* >  m_listScenes;
      std::vector< Omen::IMaterial* > m_listMaterials;

      Omen::IScene*                 m_pCurrentScene;
      Omen::IModel*                 m_pCurrentModel;
      Omen::IMesh*                  m_pCurrentMesh;
      Omen::IMaterial*              m_pCurrentMaterial;
      Omen::ITexture*               m_pCurrentTexture;

      #pragma warning(default:4251)
  };
}